import { Component, Input, Output, EventEmitter, ViewChild, TemplateRef, OnInit, HostBinding } from '@angular/core';
import { IdService } from '@farris/ui-common';
import { BsModalRef, BsModalService } from '@farris/ui-modal';
import { cloneDeep } from 'lodash-es';
import { NotifyService } from '@farris/ui-notify';
import { DesignViewModelService, DomService, FormSchemaEntityField } from '@farris/designer-services';
import { HttpClient } from '@angular/common/http';
import { ControlService } from '../../../../../../service/control.service';
import { merge } from 'lodash-es';

export interface TemplateButton {
    id: string;
    type: string;
    appearance: { class: string };
    text: string;
    click: string;
}

export interface TemplateFragemnt {
    id: string;
    name: string;
    category: string;
    content: string;
    contentItem?: string;
}

export interface TemplateField {
    id: string;
    type: string;
    name: string;
    presetType: string;
    category: string;
    binding: {
        field: string;
        path: string;
    };
    enumData: any[];
    guid?: string;
}

export interface TemplateEditorColumn {
    field: string;
    title: string;
    editor: any;
    formatter: any;
}

export interface MappingField {
    value: string;
    text: string;
}

@Component({
    selector: 'app-template-binding-editor',
    templateUrl: './template-binding-editor.component.html',
    styleUrls: ['./template-binding-editor.component.css']

})
export class TemplateBindingEditorComponent implements OnInit {

    @Output() closeModal = new EventEmitter<any>();

    @Output() submitModal = new EventEmitter<any>();

    @Input() value;

    @Input() editorParams: {
        listViewId: string,
        schemaFields: FormSchemaEntityField[],
        templateUri: string,
        viewModelId: string
    } = {
            listViewId: '',
            schemaFields: [],
            templateUri: '',
            viewModelId: ''
        };

    @ViewChild('bindingFooter') modalFooter: TemplateRef<any>;

    modalConfig = {
        title: '模板编辑器',
        width: 900,
        height: 700,
        showButtons: true
    };

    @HostBinding('class')
    class = 'd-flex f-utils-fill-flex-column h-100';

    // 代码编辑器配置
    codeEditorOptions = {
        theme: 'vs-dark',
        language: 'html',
        formatOnType: true,
        foldingStrategy: 'indentation',      // 显示缩进
        folding: true,                       // 启用代码折叠功能
        showFoldingControls: 'always',       // 默认显示装订线
        automaticLayout: true                // 监测父容器变化
    };

    presetTemplateId: string;

    templateFragements: TemplateFragemnt[];

    templateFragementCategory: Set<string>;

    templateFragementMap: Map<string, TemplateFragemnt>;

    templateFragementCategoryMap: Map<string, TemplateFragemnt[]>;

    fieldTemplateMapGroupedByCategory = new Map<string, Map<string, { bindingPath: string, template: string }>>();

    fields: TemplateField[];

    templateEditorColumns = [];

    // 模板HTML
    templateHtml = '';

    // 模板定义的样式
    templateCustomClass = '';

    // 代码编辑器实例
    monacoEditor: any;

    toolbar = { id: '', type: '', contents: [] };

    toolbarTemplate = '';

    toolbarFragement = '';

    toolbarButtonFragement = '';

    toolbarButtonClass = '';

    toolbarButtonIcons = [];

    toolbarType = '';

    toolbarWrapperFragement = '';

    defaultButtonClass: string;

    showTemplate = 'listItem';

    bindingTemplate = '';

    /** 模板单选组的枚举值 */
    templateRadioGroups = [{ value: 'listItem', name: '行模板' }, { value: 'buttons', name: '按钮模板' }];

    // 内置模板窗口
    @ViewChild('presetTplRef') presetTplRef: TemplateRef<any>;

    presetTplModal: BsModalRef;

    /** 编辑器使用的模板数据 */
    currentValue;

    /** 触发编辑器的保存操作 */
    triggerModalSave: any;

    /** 记录编辑器刚打开时的DOM actions数据。编辑器内部交互面板在操作过程中可能会修改actions节点，导致点击【取消】按钮时无法还原actions数据。所以这里记录一份原始数据，方便还原。 */
    private previousActions: any[];

    /** 记录编辑器刚打开时的DOM viewmodels数据。编辑器内部交互面板在操作过程中可能会修改viewmodels节点，导致点击【取消】按钮时无法还原viewmodels数据。所以这里记录一份原始数据，方便还原。 */
    private previousViewModels: any[];


    constructor(
        private modalServ: BsModalService,
        private notifyServ: NotifyService,
        private idService: IdService,
        private http: HttpClient,
        private domService: DomService,
        private dgVMService: DesignViewModelService,
        private controlService: ControlService) {
    }

    ngOnInit() {

        this.checkMappingFields();
        if (this.value && this.value.html) {

            // 不影响原数据
            this.currentValue = cloneDeep(this.value);

            this.presetTemplateId = this.currentValue.presetTemplateId;
            this.templateCustomClass = this.currentValue.customClass || '';
            this.templateHtml = this.currentValue.html;
            if (this.currentValue.toolbar) {
                this.toolbar = this.currentValue.toolbar;
            }
            this.toolbarTemplate = this.currentValue.toolbarTemplate;
            this.bindingTemplate = this.templateHtml;
            this.loadPresetTemplateFragements(this.presetTemplateId, this.editorParams.templateUri, this.currentValue.fields);

        }
        this.checkHasToolbarTemplate();

        this.triggerModalSave = () => this.clickConfirm();

        this.previousActions = cloneDeep(this.domService.module.actions);
        this.previousViewModels = cloneDeep(this.domService.module.viewmodels);
    }

    /**
     * 检查当前行模板中是否包含<!-- listview item toolbar -->的占位符。
     * jit生成的逻辑是将按钮模板放在<!-- listview item toolbar -->字符串的位置，所以若不包含此占位符，则页面上不展示按钮相关配置
     */
    private checkHasToolbarTemplate() {
        const listViewHtmlToolbarKey = '<!-- listview item toolbar -->';

        if (this.templateHtml && this.templateHtml.includes(listViewHtmlToolbarKey)) {
            this.templateRadioGroups = [{ value: 'listItem', name: '行模板' }, { value: 'buttons', name: '按钮模板' }];
        } else {
            this.templateRadioGroups = [{ value: 'listItem', name: '行模板' }];
            this.showTemplate = 'listItem';
        }
    }
    private loadPresetTemplateFragements(presetTemplateId: string, templateUri: string, templateFields: TemplateField[]) {
        this.http.get<any[]>(templateUri).subscribe(presetTemplates => {
            if (presetTemplates || presetTemplates.length) {
                const presetTemplate = presetTemplates.find(template => template.id === presetTemplateId);
                if (presetTemplate) {
                    this.updatePresetTemplateFragements(presetTemplate);
                    this.fields = templateFields;
                }
            }
        });
    }

    showPresetTplModal() {
        const modalConfig = {
            title: '选择内置模板',
            width: 800,
            height: 500,
            showButtons: false,
            showMaxButton: false
        };

        this.presetTplModal = this.modalServ.show(this.presetTplRef, modalConfig);
    }

    private updatePresetTemplateFragements(presetTemplate: any) {
        const {
            presetsTemplateFragements,
            toolbarFragement,
            toolbarButtonFragement,
            toolbarButtonClass,
            toolbarButtonIcons,
            toolbarType,
            toolbarWrapperFragement
        } = presetTemplate;
        this.templateFragements = presetsTemplateFragements;
        this.templateFragementCategory = this.buildPresetTempateCategorys(presetsTemplateFragements);
        this.templateFragementMap = this.buildPresetTempateFragementMap(presetsTemplateFragements);
        this.templateFragementCategoryMap = this.buildPresetTemplateFragementCategoryMap(presetsTemplateFragements);
        this.toolbarFragement = toolbarFragement;
        this.toolbarButtonFragement = toolbarButtonFragement;
        this.toolbarButtonClass = toolbarButtonClass;
        this.toolbarButtonIcons = toolbarButtonIcons;
        this.toolbarType = toolbarType;
        this.toolbarWrapperFragement = toolbarWrapperFragement;
        this.toolbar.id = `${this.editorParams.listViewId.replace(/\-/g, '')}toolbar`;
        this.toolbar.type = this.toolbarType;
    }

    /**
     * 选择内置模板
     */
    selectPresetTpl(data) {
        if (!data) {
            return;
        }
        const { id, html, presetsTemplateFragements, presetFields, customClass } = data;
        this.presetTemplateId = id;
        this.updatePresetTemplateFragements(data);
        this.templateHtml = data.html;
        this.templateCustomClass = data.customClass || '';

        this.showTemplate = 'listItem';
        this.fields = this.buildPresetTemplateFields(presetFields);
        this.toolbar.contents = [];
        this.updateTemplateHtml();

        this.presetTplModal.close();
    }

    private buildPresetTempateFragementMap(presetsTemplateFragements: TemplateFragemnt[]) {
        const presetTempateFragementMap = new Map<string, TemplateFragemnt>();
        presetsTemplateFragements
            .reduce<Map<string, TemplateFragemnt>>((fragementMap: Map<string, TemplateFragemnt>, fragement: TemplateFragemnt) => {
                if (!fragementMap.has(fragement.id)) {
                    fragementMap.set(fragement.id, fragement);
                }
                return fragementMap;
            }, presetTempateFragementMap);
        return presetTempateFragementMap;
    }

    private buildPresetTempateCategorys(presetsTemplateFragements: TemplateFragemnt[]) {
        const categorys: Set<string> = new Set<string>();
        presetsTemplateFragements
            .reduce<Set<string>>((fragementCategory: Set<string>, fragement: TemplateFragemnt) => {
                fragementCategory.add(fragement.category);
                return fragementCategory;
            }, categorys);
        return categorys;
    }

    private buildPresetTemplateFragementCategoryMap(presetsTemplateFragements: TemplateFragemnt[]) {
        const fragementCategoryMap: Map<string, TemplateFragemnt[]> = new Map<string, TemplateFragemnt[]>();
        presetsTemplateFragements
            .reduce<Map<string, TemplateFragemnt[]>>((currentMap: Map<string, TemplateFragemnt[]>, fragement: TemplateFragemnt) => {
                if (!currentMap.has(fragement.category)) {
                    currentMap.set(fragement.category, []);
                }
                const fragments = currentMap.get(fragement.category);
                fragments.push(fragement);
                return currentMap;
            }, fragementCategoryMap);
        return fragementCategoryMap;
    }

    private generateTemplateHtml(
        template: string,
        presetsTemplateFragements: TemplateFragemnt[],
        templateFields: TemplateField[],
        changedField: TemplateField): string {
        const fieldsGroupedByCategory = new Map<string, TemplateField[]>();

        templateFields.reduce<Map<string, TemplateField[]>>((groups, field) => {
            const { category } = field;
            if (!groups.has(category)) {
                groups.set(category, []);
            }
            const fieldsInSpecialCategory = groups.get(category);
            fieldsInSpecialCategory.push(field);
            return groups;
        }, fieldsGroupedByCategory);

        const fieldTemplateMapGroupedByCategory = this.parseFieldTemplates(template, fieldsGroupedByCategory);
        this.templateFragementCategory.forEach(category => {
            let fieldsFragementsInSpecialCategory = [''];
            if (fieldsGroupedByCategory.has(category)) {
                const fieldsInSpecialCategory = fieldsGroupedByCategory.get(category);
                const fieldTempalteMapInSpecialCategory = fieldTemplateMapGroupedByCategory.get(category);
                fieldsFragementsInSpecialCategory = fieldsInSpecialCategory.map(field => {
                    if (fieldTempalteMapInSpecialCategory && fieldTempalteMapInSpecialCategory.has(field.id)) {
                        const fieldTemplateItem = fieldTempalteMapInSpecialCategory.get(field.id);
                        if (fieldTemplateItem && (!changedField || changedField.id !== field.id)) {
                            return fieldTemplateItem.template;
                        }
                    }
                    const fragementType = field.presetType;
                    const fragement = this.templateFragementMap.get(fragementType);
                    if (fragement) {
                        let fieldContent = fragement.content;
                        if (fragement.contentItem) {
                            const contentItem = fragement.contentItem;
                            if (field.enumData && field.enumData.length) {
                                const contentItemFragements = field.enumData.map(({ value, name }) => {
                                    return contentItem.replace('${preset:enumValue}', value)
                                        .replace('${preset:enumText}', `\${${field.id}:${value}:text}`);
                                });
                                fieldContent = fieldContent.replace('${preset:items}', contentItemFragements.join(''));
                            }
                        }
                        return fieldContent.replace('${preset:field}', field.id)
                            .replace('${preset:value}', '${' + field.id + ':value}')
                            .replace('${preset:label}', '${' + field.id + ':label}')
                            .replace('${preset:field}', field.id);
                    }
                });
            }
            const fieldsContentInSpecialCategory = fieldsFragementsInSpecialCategory.join('');
            const regString = `<!-- begin ${category} -->[\\S\\s]*<!-- end ${category} -->`;
            const replaceRegExp = new RegExp(regString, 'g');
            template = template.replace(replaceRegExp,
                `<!-- begin ${category} -->${fieldsContentInSpecialCategory}<!-- end ${category} -->`);
        });
        return template;
    }

    private parseFieldTemplates(template: string, fieldsGroupedByCategory: Map<string, TemplateField[]>)
        : Map<string, Map<string, { bindingPath: string, template: string }>> {
        const fieldTemplateMapGroupedByCategory = new Map<string, Map<string, { bindingPath: string, template: string }>>();
        fieldsGroupedByCategory.forEach((fieldsInSpecialCategory, category) => {
            const fieldTemplateMap = new Map<string, { bindingPath: string, template: string }>();
            fieldsInSpecialCategory.reduce<Map<string, { bindingPath: string, template: string }>>((previousValue, field) => {
                const regString = `<!-- ${field.id} -->[\\S\\s]*<!-- ${field.id} -->`;
                const searchingRegExp = new RegExp(regString);
                const matchingResult = template.match(searchingRegExp);
                if (matchingResult && matchingResult.length) {
                    const matchedTemplate = matchingResult[0];
                    if (matchedTemplate) {
                        previousValue.set(field.id, { bindingPath: field.binding.path, template: matchedTemplate });
                    }
                }
                return previousValue;
            }, fieldTemplateMap);
            fieldTemplateMapGroupedByCategory.set(category, fieldTemplateMap);
        });
        return fieldTemplateMapGroupedByCategory;
    }

    private buildPresetTemplateFields(presetFields: TemplateField[]): TemplateField[] {
        const fields: TemplateField[] = [];
        presetFields.forEach(presetField => {
            fields.push({
                id: presetField.id,
                type: 'TemplateField',
                name: presetField.name,
                presetType: presetField.presetType,
                category: presetField.category,
                binding: {
                    field: '',
                    path: ''
                },
                enumData: []
            });
        });
        return fields;
    }

    private generateToolbarTemplate(
        toolbarWrapperFragement: string,
        toolbarFragement: string,
        toolbarButtonFragement: string,
        buttons: TemplateButton[]
    ): string {
        let toolbarTemplate = toolbarFragement;
        let buttonsFragment = [''];
        if (toolbarButtonFragement && buttons && buttons.length) {
            buttonsFragment = buttons.map(button => {
                return toolbarButtonFragement.replace('${preset:button-class}', button.appearance.class)
                    .replace('${preset:button-text}', '${' + button.id + ':text}')
                    .replace('${preset:toolbar-click-callback}', `${this.toolbar.id}ClickHandler`)
                    .replace('${preset:button-id}', button.id);
                // .replace('${preset:button-action}', button.click);
            });
        }
        const buttonsTemplate = buttonsFragment.join('');

        if (toolbarTemplate && buttonsFragment.length) {
            const regString = `<!-- begin buttons -->[\\S\\s]*<!-- end buttons -->`;
            const replaceRegExp = new RegExp(regString, 'g');
            toolbarTemplate = toolbarTemplate.replace(replaceRegExp,
                `<!-- begin buttons -->${buttonsTemplate}<!-- end buttons -->`);
        }

        if (toolbarTemplate) {
            toolbarTemplate = toolbarTemplate.replace('${preset:toolbar-config-variable}', `${this.toolbar.id}config`)
                .replace('${preset:toolbar-click-callback}', `${this.toolbar.id}ClickHandler`);
        }

        if (toolbarWrapperFragement && toolbarTemplate.length) {
            const regString = `<!-- begin toolbar -->[\\S\\s]*<!-- end toolbar -->`;
            const replaceRegExp = new RegExp(regString, 'g');
            toolbarTemplate = toolbarWrapperFragement.replace(replaceRegExp,
                `<!-- begin toolbar -->${toolbarTemplate}<!-- end toolbar -->`);
        }

        return toolbarTemplate;
    }

    cancelPresetTpl() {
        this.presetTplModal.close();
    }

    onMonacoInit($event) {
        this.monacoEditor = $event.editor;
        // 监听代码编辑器的文本变化，重新组装变量映射
        this.monacoEditor.onDidChangeModelContent(() => {
            if (this.showTemplate === 'listItem') {
                this.templateHtml = this.bindingTemplate;
            } else {
                this.toolbarTemplate = this.bindingTemplate;
            }

            this.checkHasToolbarTemplate();
        });
    }

    clickCancel() {
        this.domService.module.actions = this.previousActions;
        this.domService.module.viewmodels = this.previousViewModels;
        this.closeModal.emit();
    }

    /**
     * 点击确定，保存并关闭弹窗。
     * 返回是否成功保存，用于交互面板判断是否能跳转到代码视图。
     */
    clickConfirm(): boolean {

        if (!this.templateHtml) {
            this.submitModal.emit({ value: null });
            return true;
        }

        const tplVarList = [];
        const bindingSchemaFields = [];
        if (this.fields) {
            for (const field of this.fields) {
                if (!field.binding.field) {
                    this.notifyServ.warning('请选择变量【' + field.id + '】的绑定字段');
                    return false;
                }
                const schemaField = this.editorParams.schemaFields.find(targetField => targetField.id === field.binding.field);
                bindingSchemaFields.push(schemaField);
                if (schemaField) {
                    field.binding.path = schemaField.bindingPath;
                    field.enumData = schemaField.type.enumValues;
                }
                if (!field.binding.path) {
                    this.notifyServ.warning('请选择变量【' + field.id + '】的绑定字段');
                    return false;
                }
                if (tplVarList.includes(field.id)) {
                    this.notifyServ.warning('变量【' + field.id + '】重复，请修改');
                    return false;
                }
                tplVarList.push(field.id);
            }
        }

        // 将绑定字段同步到视图模型
        this.addBindingFieldsToViewModel(bindingSchemaFields);

        // 删除视图模型中已被移除的字段
        this.removeBindingFieldsInViewModel(bindingSchemaFields);

        this.submitModal.emit({
            value: {
                html: this.templateHtml,
                fields: this.fields || [],
                customClass: this.templateCustomClass,
                toolbar: this.toolbar,
                toolbarTemplate: this.toolbarTemplate,
                presetTemplateId: this.presetTemplateId,
            }
        });
        return true;
    }

    private addBindingFieldsToViewModel(bindingSchemaFields: FormSchemaEntityField[]) {
        const dgVM = this.dgVMService.getDgViewModel(this.editorParams.viewModelId);
        if (!dgVM) {
            return;
        }
        bindingSchemaFields.forEach(bindingField => {
            if (!dgVM.fields.find(f => f.id === bindingField.id)) {
                const newField = merge({}, bindingField, { groupId: null, groupName: null });

                dgVM.addField(newField);
            }
        });
    }

    private removeBindingFieldsInViewModel(bindingSchemaFields: FormSchemaEntityField[]) {
        const dgVM = this.dgVMService.getDgViewModel(this.editorParams.viewModelId);
        if (!dgVM) {
            return;
        }
        const newFieldIds = bindingSchemaFields.map(field => field.id);
        const deletedFields = dgVM.fields.filter(f => !newFieldIds.includes(f.id));
        if (deletedFields && deletedFields.length > 0) {
            const deletedFieldIds = deletedFields.map(field => field.id);
            dgVM.removeField(deletedFieldIds);
        }
    }
    private checkMappingFields() {
        for (const field of this.editorParams.schemaFields) {
            if (!field.bindingPath) {
                this.notifyServ.warning('字段缺少bindingPath属性，请先更新表单Schema。');
                this.closeModal.emit();
                return;
            }
        }
    }

    private updateTemplateField(rowData: any, rowIndex: number) {
        // const id = rowData.id;
        const templateField = this.fields[rowIndex];
        if (templateField) {
            Object.assign(templateField, rowData);
            const presetFieldFragement = this.templateFragementMap.get(rowData.presetType);
            if (presetFieldFragement) {
                templateField.category = presetFieldFragement.category;
            }
            if (templateField.binding && templateField.binding.field) {
                const schemaField = this.editorParams.schemaFields.find(targetField => targetField.id === templateField.binding.field);
                if (schemaField) {
                    templateField.binding.path = schemaField.bindingPath;
                    templateField.enumData = cloneDeep(schemaField.type.enumValues);
                }
            }
        }
    }

    private updateTemplateHtml(variableItem?: TemplateField) {
        this.templateHtml = this.generateTemplateHtml(this.templateHtml, this.templateFragements, this.fields, variableItem);
        this.toolbarTemplate = this.generateToolbarTemplate(this.toolbarWrapperFragement, this.toolbarFragement,
            this.toolbarButtonFragement, this.toolbar.contents);
        this.bindingTemplate = this.showTemplate === 'listItem' ? this.templateHtml : this.toolbarTemplate;

        this.checkHasToolbarTemplate();
    }

    private onEndEdit({ column, rowData, rowIndex, value }) {
        this.updateTemplateField(rowData, rowIndex);
        this.updateTemplateHtml();
    }

    onVariableFieldChanged(variableItem: TemplateField) {
        const index = this.fields.findIndex(field => field.id === variableItem.id);
        this.updateTemplateField(variableItem, index);
        this.updateTemplateHtml(variableItem);
    }

    onVariableFieldAdded(category: string) {
        const prefix = this.idService.guid().substr(0, 4);
        const id = `${category}-${prefix}`;
        const newItem = {
            id,
            type: 'TemplateField',
            name: '',
            presetType: '',
            category,
            binding: {
                field: '',
                path: ''
            },
            enumData: []
        };
        this.fields = [...this.fields, newItem];
        // this.fields.push(newItem);
    }

    onVariableFieldRemoved(variableItem: TemplateField) {
        const index = this.fields.findIndex(field => field.id === variableItem.id);
        if (index > -1) {
            this.fields.splice(index, 1);
            this.fields = [...this.fields];
            this.updateTemplateHtml();
        }
    }

    moveUpVariableField(variableItem: TemplateField) {
        const index = this.fields.findIndex(field => field.id === variableItem.id);
        if (index > 0) {
            const currentVariableField = this.fields[index];
            const preVariableField = this.fields[index - 1];
            this.fields[index - 1] = currentVariableField;
            this.fields[index] = preVariableField;
            this.fields = [...this.fields];
            this.updateTemplateHtml();
        }
    }

    moveDownVariableField(variableItem: TemplateField) {
        const index = this.fields.findIndex(field => field.id === variableItem.id);
        if (index < this.fields.length - 1) {
            const currentVariableField = this.fields[index];
            const nextVariableField = this.fields[index + 1];
            this.fields[index + 1] = currentVariableField;
            this.fields[index] = nextVariableField;
            this.fields = [...this.fields];
            this.updateTemplateHtml();
        }
    }

    onButtonAdded() {
        let presetButtonIcon = '';
        if (this.toolbarButtonIcons && this.toolbarButtonIcons.length) {
            const iconIndex = Math.min(this.toolbar.contents.length, this.toolbarButtonIcons.length - 1);
            presetButtonIcon = this.toolbarButtonIcons[iconIndex];
        }
        const metadata = this.controlService.getControlMetaData('ToolBarItem');
        const radomNum = Math.random().toString().substr(2, 4);
        metadata.id = 'toolBarItem_' + radomNum;
        metadata.text = '按钮_' + radomNum;
        metadata.appearance = {
            class: this.toolbarButtonClass ? `${this.toolbarButtonClass} ${presetButtonIcon}` : ''
        };
        this.toolbar.contents = [...this.toolbar.contents, metadata];
        this.updateTemplateHtml();
    }

    onButtonRemoved(templateButton: TemplateButton) {
        const index = this.toolbar.contents.findIndex(item => item.id === templateButton.id);
        if (index > -1) {
            this.toolbar.contents.splice(index, 1);
            this.toolbar.contents = [...this.toolbar.contents];
            this.updateTemplateHtml();
        }
    }

    moveUpTemplateButton(templateButton: TemplateButton) {
        const index = this.toolbar.contents.findIndex(item => item.id === templateButton.id);
        if (index > 0) {
            const currentButton = this.toolbar.contents[index];
            const preButton = this.toolbar.contents[index - 1];
            this.toolbar.contents[index - 1] = currentButton;
            this.toolbar.contents[index] = preButton;
            this.toolbar.contents = [...this.toolbar.contents];
            this.updateTemplateHtml();
        }
    }

    moveDownTemplateButton(templateButton: TemplateButton) {
        const index = this.toolbar.contents.findIndex(item => item.id === templateButton.id);
        if (index < this.toolbar.contents.length - 1) {
            const currentButton = this.toolbar.contents[index];
            const nextButton = this.toolbar.contents[index + 1];
            this.toolbar.contents[index + 1] = currentButton;
            this.toolbar.contents[index] = nextButton;
            this.toolbar.contents = [...this.toolbar.contents];
            this.updateTemplateHtml();
        }
    }

    changeShowTemplateMode() {
        this.bindingTemplate = this.showTemplate === 'listItem' ? this.templateHtml : this.toolbarTemplate;
    }
}
